/**
 * 
 */
package it.polimi.cg16.net;

import it.polimi.cg16.controller.PlayerController;
import it.polimi.cg16.controller.Server;
import it.polimi.cg16.controller.Starter;
import it.polimi.cg16.exceptions.InactivePlayerException;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Timer;

/**
 * @author Andrea & Michele
 * 
 */
public class SocketServer implements Runnable {
    private static final Logger LOGGER = Logger.getGlobal();

    private PrintStream ps = System.out;

    // Network Attributes
    private ServerSocket providerSocket;

    private GameDatabase database;
    private Reactivator reactivator;
    protected Starter starter;
    private int numberOfPlayer;

    Timer t1;

    public SocketServer(GameDatabase database, Reactivator reactivator, Starter starter) {
        this.database = database;
        this.reactivator = reactivator;
        this.starter = starter;
    }

    public void run() {
        try {
            // 1. creating a server socket
            providerSocket = new ServerSocket(2004);
            // 2. Wait for connection
            ps.println("Waiting for connection");
            while (true) {
                numberOfPlayer = 0;
                while (database.waitPlayerSize() < Server.MAX_PLAYER) {
                    while (database.waitPlayerSize() < Server.MIN_PLAYER) {
                        connection();
                    }
                    t1 = new Timer(Server.GAME_START_TIME_OUT, new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            starter.startGame();
                        }
                    });
                    t1.setRepeats(false);
                    t1.start();
                    connection();
                    t1.restart();
                }
                t1.stop();
                starter.startGame();
            }

        } catch (IOException ioException) {
            LOGGER.log(Level.FINE, "context", ioException);
        }

    }

    /**
     * Create the connection
     * 
     * @throws IOException
     */
    private void connection() throws IOException {
        SocketAdapter socketAdapter = new SocketAdapter(providerSocket.accept());
        String username = null;
        try {
            username = socketAdapter.readString();
        } catch (InactivePlayerException e) {
            LOGGER.log(Level.FINE, "context", e);
        }

        if (database.hasPlayer(username)) {
            PlayerController player = database.getPlayer(username);
            socketAdapter.setPlayerController(player);
            reactivator.reActivatePlayer(player, socketAdapter);
            Thread t = new Thread(reactivator);
            t.start();
        } else if (database.isActive(username)) {
            socketAdapter.sendMessage("bye");
        } else {
            PlayerController player = new PlayerController(socketAdapter, numberOfPlayer, username);
            database.addPlayer(player);
            socketAdapter.setPlayerController(player);
        }
        numberOfPlayer++;

    }

}
